import os
import pandas as pd
from datetime import datetime as dt
from concurrent.futures import ThreadPoolExecutor


class Logger():
    def __init__(self, file_name) -> None:
        self.file_name = file_name
    
    def info(self, msg):
        t = dt.now().strftime("%Y-%m-%d %H:%M:%S")
        with open(self.file_name, 'a') as f:
            f.write(t + "[INFO] " + str(msg) + '\n')
    
    def error(self, msg):
        t = dt.now().strftime("%Y-%m-%d %H:%M:%S")
        with open(self.file_name, 'a') as f:
            f.write(t + "[ERROR] " + str(msg) + '\n')

logger = Logger("./docker.log")

class Image():
    def __init__(self, name, tag, _id) -> None:
        self.name = name
        self.tag = tag
        self.id = _id[:12]
        self.res = ""
    
    def remove(self):
        res = os.popen("docker rmi %s:%s" % (self.name, self.tag)).read()
        if "error" in res.lower():
            return False
        return True


class Container():
    def __init__(self, image_id) -> None:
        self.image_id = image_id.lower()
        self.id = None
    
    def start(self):
        res = os.popen("docker run -itd %s bash" % self.image_id).read().strip()
        if res:
            self.id = res[:12]
            logger.info('container %s started' % self.id)
        else:
            logger.error("container start failed")
    
    def run(self, cmd):
        res = os.popen('docker exec %s %s' % (self.id, cmd)).read()
        if 'error' in res.lower() or 'fail' in res.lower():
            logger.error('exec %s failed' % cmd)
        return res

    def remove(self):
        res = os.popen("docker stop %s && docker rm %s " % (self.id, self.id)).read()
        if 'error' in res.lower():
            logger.error("remove %s failed" % self.id)
            return
        logger.info("remove %s success" % self.id)


class Excutor():
    def __init__(self, imgs, pool_size=5) -> None:
        self.pool = ThreadPoolExecutor(max_workers=pool_size)
        self.imgs = imgs
        self.results = []
    
    def run(self, cmd):
        for i in range(len(self.imgs)):
            self.results.append(self.pool.submit(self._run, i, cmd))
    
    def _run(self, index, cmd):
        con = Container(self.imgs[index].id)
        con.start()
        res = con.run(cmd)
        con.remove()
        self.imgs[index].res = res
        return True
    
    def wait(self):
        while True:
            ends = 0
            for i in self.results:
                if i.result():
                    ends += 1
            if ends == len(self.results):
                break


def get_images(cmd="docker images"):
    res = os.popen(cmd).read()
    images = []
    for line in res.split("\n"):
        tmp = [i for i in line.split(" ") if i]
        if len(tmp) < 2:
            continue
        if tmp[2].lower() == 'image':continue
        images.append(Image(tmp[0], tmp[1], tmp[2]))
    return images


if __name__ == "__main__":
    images = get_images()
    need_del = []
    excutor = Excutor(images, 20)
    excutor.run("cat /etc/*release")
    excutor.wait()
    docker_info = []
    for img in images:
        if 'CentOS'.lower() in img.res.lower():
            version = ''
            for line in img.res.split('\n'):
                if 'release' in line:
                    version = line.split('release')[1].strip()
                    break
                if line.startswith("VERSION="):
                    version = line.split("=")[1].strip()
                    break
            os_and_version = 'CentOS' + version
            img.os_and_version = os_and_version
            print(img.name, img.tag, img.id, img.os_and_version)
            docker_info.append({
                "name": img.name, "tag": img.tag,
                "id": img.id, "os_and_version": img.os_and_version
            })
        elif "Ubuntu" in img.res:
            version = ''
            for line in img.res.split('\n'):
                if line.startswith("VERSION="):
                    version = line.split("=")[1].strip()
                    break
            img.os_and_version = "Ubuntu" + version
            print(img.name, img.tag, img.id, img.os_and_version)
            docker_info.append({
                "name": img.name, "tag": img.tag,
                "id": img.id, "os_and_version": img.os_and_version
            })
        elif "openEuler" in img.res:
            version = ''
            for line in img.res.split('\n'):
                if line.startswith("VERSION="):
                    version = line.split("=")[1].strip()
                    break
            img.os_and_version = "openEuler" + version
            print(img.name, img.tag, img.id, img.os_and_version)
            docker_info.append({
                "name": img.name, "tag": img.tag,
                "id": img.id, "os_and_version": img.os_and_version
            })
        else:
            os_name = ''
            version = ''
            for line in img.res.split('\n'):
                if line.startswith("VERSION=") and version == '':
                    version = line.split("=")[1].strip()
                if line.startswith("NAME=") and os_name == '':
                    os_name = line.split("=")[1].strip()
            img.os_and_version = os_name + version
            print(img.name, img.tag, img.id, img.os_and_version)
            docker_info.append({
                "name": img.name, "tag": img.tag,
                "id": img.id, "os_and_version": img.os_and_version
            })
    info = pd.DataFrame(docker_info)
    info.to_csv("docker_info.csv", index=0)
